// Test for HashTable

#include <gtest/gtest.h>
#include "hashtable.h"
#include "sutil.h"		// for strhash


const int HashBufSize = (1<<4)-1;

class HashTest : public testing::Test {
protected:
	virtual void SetUp() {
		ht_init(&ht, &vtbl);
		ht_resize(&ht, HashBufSize);
	}

	virtual void TearDown() {
		ht_term(&ht);
	}

	HashTable ht;
	static HashVTbl vtbl;
};


static int check(const void* ptr, const void* key) {
	const char* val = (const char*)ptr;
	const char* str = (const char*)key;
	return strcmp(val, str) == 0;
}

HashVTbl HashTest::vtbl = {
	malloc,
	free,
	(unsigned int (*)(const void*))strhash,
	check,
};

//=============================================================================

static const char str[] = "This is a test string.";

TEST_F(HashTest, AddElem) {
	ht_find(&ht, str);
	EXPECT_TRUE(ht_find(&ht, str) == NULL) << "not found before add";

	ht_add_direct(&ht, str, (void*)str);
	EXPECT_TRUE(ht_find(&ht, str) != NULL) << "found after add";
}

TEST_F(HashTest, Resize) {
	ht_add_direct(&ht, str, (void*)str);
	ht_resize(&ht, HashBufSize * 2 + 1);
	EXPECT_TRUE(ht_find(&ht, str) != NULL) << "found after resize";

	ht_resize(&ht, 0);
	EXPECT_TRUE(ht_find(&ht, str) == NULL) << "resize(0) is clear-all";
}

TEST_F(HashTest, Remove) {
	ht_add_direct(&ht, str, (void*)str);
	ht_remove(&ht, str);
	EXPECT_TRUE(ht_find(&ht, str) == NULL) << "not found after remove";
}

TEST_F(HashTest, ClearEntry) {
	ht_add_direct(&ht, str, (void*)str);
	ht_clear_all(&ht);
	EXPECT_TRUE(ht_find(&ht, str) == NULL) << "not found after clear-entry";
}
